
/*---------------------------------------------------------------------------
 *
 * Ryu 浮点输出用于双精度。
 *
 * Portions Copyright (c) 2018-2022, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *	  src/common/d2s.c
 *
 * This is a modification of code taken from github.com/ulfjack/ryu under the
 * terms of the Boost license (not the Apache license). The original copyright
 * notice follows:
 *
 * Copyright 2018 Ulf Adams
 *
 * The contents of this file may be used under the terms of the Apache
 * License, Version 2.0.
 *
 *     (See accompanying file LICENSE-Apache or copy at
 *      http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Alternatively, the contents of this file may be used under the terms of the
 * Boost Software License, Version 1.0.
 *
 *     (See accompanying file LICENSE-Boost or copy at
 *      https://www.boost.org/LICENSE_1_0.txt)
 *
 * Unless required by applicable law or agreed to in writing, this software is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.
 *
 *---------------------------------------------------------------------------
 */

/*
 *  运行时编译器选项：
 *
 *  -DRYU_ONLY_64_BIT_OPS 避免使用 uint128 或 64 位内建函数。较慢，
 *      具体取决于你的编译器。
 */

#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif

#include "common/shortest_dec.h"

/*
 * 为了一致性，我们仅在 PG 其他地方也使用 128 位类型时才使用 128 位类型，
 * 尽管在这里使用它们不会担心其他地方的对齐问题。
 */
#if !defined(HAVE_INT128) && defined(_MSC_VER) \
	&& !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64)
#define HAS_64_BIT_INTRINSICS
#endif

#include "ryu_common.h"
#include "digit_table.h"
#include "d2s_full_table.h"
#include "d2s_intrinsics.h"

#define DOUBLE_MANTISSA_BITS 52
#define DOUBLE_EXPONENT_BITS 11
#define DOUBLE_BIAS 1023

#define DOUBLE_POW5_INV_BITCOUNT 122
#define DOUBLE_POW5_BITCOUNT 121


static inline uint32 fc_pow5Factor(uint64 fc_value)
{
	uint32		fc_count = 0;

	for (;;)
	{
		Assert(fc_value != 0);
		const uint64 fc_q = div5(fc_value);
		const uint32 fc_r = (uint32) (fc_value - 5 * fc_q);

		if (fc_r != 0)
			break;

		fc_value = fc_q;
		++fc_count;
	}
	return fc_count;
}

/* 返回 true 如果值能被 5^p 整除。 */
static inline bool fc_multipleOfPowerOf5(const uint64 fc_value, const uint32 fc_p)
{
	/*
	 * 我尝试了对 p 的案例区分，但没有性能差异。
	 */
	return fc_pow5Factor(fc_value) >= fc_p;
}

/* 返回 true 如果值能被 2^p 整除。 */
static inline bool fc_multipleOfPowerOf2(const uint64 fc_value, const uint32 fc_p)
{
	/* return __builtin_ctzll(value) >= p; */
	return (fc_value & ((UINT64CONST(1) << fc_p) - 1)) == 0;
}

/*
 * 我们需要进行 64x128 位乘法和后续的 128 位移位。
 *
 * 乘法：
 *
 *    64 位因子是可变的并传入，128 位因子来自查找表。我们知道，
 *    64 位因子只有 55 个有效位（即，最高的 9 位是零）。128 位因子
 *    只有 124 个有效位（即，最高的 4 位是零）。
 *
 * 移位：
 *
 *    原则上，乘法结果需要 55 + 124 = 179 位来表示。然而，我们随后
 *    将这个值向右移动 j 位，且 j 至少为 j >= 115，因此结果保证可以
 *    套入 179 - 115 = 64 位。这意味着我们只需要 64x128 位乘法的
 *    最高 64 个有效位。
 *
 * 有几种方法可以实现这一点：
 *
 *  1. 最佳情况：编译器暴露 128 位类型。
 *     我们执行两个 64x64 位乘法，将较低结果的高 64 位加到较高结果上，
 *     并向右移 j - 64 位。
 *
 *     我们显式地将 64 位转换为 128 位，以便编译器可以知道这些
 *     仅是 64 位输入，并可以将这些映射到可能的最佳汇编指令序列。
 *     x86-64 机器恰好有与 64x64 位乘法和 128 位移位相匹配的汇编指令。
 *
 *  2. 第二最佳情况：编译器暴露用于 x86-64 汇编指令的内建函数，
 *     在 1 中提到过。
 *
 *  3. 我们只有返回结果的低 64 位的 64x64 位指令，即我们必须使用纯 C。
 *
 *     我们的输入小于完整宽度，因此我们有三种选择：
 *     a. 忽略这一事实并手动实现内建函数。
 *     b. 将两个因子拆分为 31 位块，保证没有内部溢出，但在开始时
 *        需要额外的工作（除非我们更改查找表）。
 *     c. 只将第一个因子拆分为 31 位块，这也保证没有内部溢出，
 *        但由于中间结果未对齐，需要额外的工作。
 */
#if defined(HAVE_INT128)

/* 最佳情况：使用 128 位类型。 */
static inline uint64 fc_mulShift(const uint64 fc_m, const uint64 *const fc_mul, const int32 fc_j)
{
	const uint128 fc_b0 = ((uint128) fc_m) * fc_mul[0];
	const uint128 fc_b2 = ((uint128) fc_m) * fc_mul[1];

	return (uint64) (((fc_b0 >> 64) + fc_b2) >> (fc_j - 64));
}

static inline uint64 fc_mulShiftAll(const uint64 fc_m, const uint64 *const fc_mul, const int32 fc_j,
			uint64 *const fc_vp, uint64 *const fc_vm, const uint32 fc_mmShift)
{
	*fc_vp = fc_mulShift(4 * fc_m + 2, fc_mul, fc_j);
	*fc_vm = fc_mulShift(4 * fc_m - 1 - fc_mmShift, fc_mul, fc_j);
	return fc_mulShift(4 * fc_m, fc_mul, fc_j);
}

#elif defined(HAS_64_BIT_INTRINSICS)

static inline uint64 mulShift(const uint64 m, const uint64 *const mul, const int32 j)
{
	/* m 最大 55 位 */
	uint64		high1;

	/* 128 */
	const uint64 low1 = umul128(m, mul[1], &high1);

	/* 64 */
	uint64		high0;
	uint64		sum;

	/* 64 */
	umul128(m, mul[0], &high0);
	/* 0 */
	sum = high0 + low1;

	if (sum < high0)
	{
		++high1;
		/* 溢出到 high1 */
	}
	return shiftright128(sum, high1, j - 64);
}

static inline uint64 mulShiftAll(const uint64 m, const uint64 *const mul, const int32 j,
			uint64 *const vp, uint64 *const vm, const uint32 mmShift)
{
	*vp = mulShift(4 * m + 2, mul, j);
	*vm = mulShift(4 * m - 1 - mmShift, mul, j);
	return mulShift(4 * m, mul, j);
}

#else							/* // !defined(HAVE_INT128) &&
								 * !defined(HAS_64_BIT_INTRINSICS) */

static inline uint64 mulShiftAll(uint64 m, const uint64 *const mul, const int32 j,
			uint64 *const vp, uint64 *const vm, const uint32 mmShift)
{
	m <<= 1;					/* m 最大 55 位 */

	uint64		tmp;
	const uint64 lo = umul128(m, mul[0], &tmp);
	uint64		hi;
	const uint64 mid = tmp + umul128(m, mul[1], &hi);

	hi += mid < tmp;			/* 溢出到高位 */

	const uint64 lo2 = lo + mul[0];
	const uint64 mid2 = mid + mul[1] + (lo2 < lo);
	const uint64 hi2 = hi + (mid2 < mid);

	*vp = shiftright128(mid2, hi2, j - 64 - 1);

	if (mmShift == 1)
	{
		const uint64 lo3 = lo - mul[0];
		const uint64 mid3 = mid - mul[1] - (lo3 > lo);
		const uint64 hi3 = hi - (mid3 > mid);

		*vm = shiftright128(mid3, hi3, j - 64 - 1);
	}
	else
	{
		const uint64 lo3 = lo + lo;
		const uint64 mid3 = mid + mid + (lo3 < lo);
		const uint64 hi3 = hi + hi + (mid3 < mid);
		const uint64 lo4 = lo3 - mul[0];
		const uint64 mid4 = mid3 - mul[1] - (lo4 > lo3);
		const uint64 hi4 = hi3 - (mid4 > mid3);

		*vm = shiftright128(mid4, hi4, j - 64);
	}

	return shiftright128(mid, hi, j - 64 - 1);
}

#endif							/* // HAS_64_BIT_INTRINSICS */

static inline uint32 fc_decimalLength(const uint64 fc_v)
{
	/* 这比循环稍快。 */
	/* 平均输出长度为 16.38 位数字，因此我们从高到低检查。 */
	/* 函数前置条件：v 不是 18、19 或 20 位数字。 */
	/* （17 位数足以进行回传。） */
	Assert(fc_v < 100000000000000000L);
	if (fc_v >= 10000000000000000L)
	{
		return 17;
	}
	if (fc_v >= 1000000000000000L)
	{
		return 16;
	}
	if (fc_v >= 100000000000000L)
	{
		return 15;
	}
	if (fc_v >= 10000000000000L)
	{
		return 14;
	}
	if (fc_v >= 1000000000000L)
	{
		return 13;
	}
	if (fc_v >= 100000000000L)
	{
		return 12;
	}
	if (fc_v >= 10000000000L)
	{
		return 11;
	}
	if (fc_v >= 1000000000L)
	{
		return 10;
	}
	if (fc_v >= 100000000L)
	{
		return 9;
	}
	if (fc_v >= 10000000L)
	{
		return 8;
	}
	if (fc_v >= 1000000L)
	{
		return 7;
	}
	if (fc_v >= 100000L)
	{
		return 6;
	}
	if (fc_v >= 10000L)
	{
		return 5;
	}
	if (fc_v >= 1000L)
	{
		return 4;
	}
	if (fc_v >= 100L)
	{
		return 3;
	}
	if (fc_v >= 10L)
	{
		return 2;
	}
	return 1;
}

/* 一个浮动的小数，表示 m * 10^e。 */
typedef struct floating_decimal_64
{
	uint64		mantissa;
	int32		exponent;
} floating_decimal_64;

static inline floating_decimal_64
fc_d2d(const uint64 fc_ieeeMantissa, const uint32 fc_ieeeExponent)
{
	int32		fc_e2;
	uint64		fc_m2;

	if (fc_ieeeExponent == 0)
	{
		/* 我们减去 2，以便边界计算有 2 位额外的位。 */
		fc_e2 = 1 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
		fc_m2 = fc_ieeeMantissa;
	}
	else
	{
		fc_e2 = fc_ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
		fc_m2 = (UINT64CONST(1) << DOUBLE_MANTISSA_BITS) | fc_ieeeMantissa;
	}

#if STRICTLY_SHORTEST
	const bool	even = (m2 & 1) == 0;
	const bool	acceptBounds = even;
#else
	const bool	fc_acceptBounds = false;
#endif

	/* 第 2 步：确定合法小数表示的区间。 */
	const uint64 fc_mv = 4 * fc_m2;

	/* 隐式 bool -> int 转换。真为 1，假为 0。 */
	const uint32 fc_mmShift = fc_ieeeMantissa != 0 || fc_ieeeExponent <= 1;

	/* 我们将这样计算 mp 和 mm： */
	/* uint64 mp = 4 * m2 + 2; */
	/* uint64 mm = mv - 1 - mmShift; */

	/* 第 3 步：使用 128 位算术转换为小数幂基。 */
	uint64		fc_vr,
				fc_vp,
				fc_vm;
	int32		fc_e10;
	bool		fc_vmIsTrailingZeros = false;
	bool		fc_vrIsTrailingZeros = false;

	if (fc_e2 >= 0)
	{
		/*
		 * 我尝试过为 q == 0 特殊处理，但对
		 * 性能没有影响。
		 *
		 * 这个表达式比 max(0, log10Pow2(e2) - 1) 稍快。
		 */
		const uint32 fc_q = log10Pow2(fc_e2) - (fc_e2 > 3);
		const int32 fc_k = DOUBLE_POW5_INV_BITCOUNT + pow5bits(fc_q) - 1;
		const int32 fc_i = -fc_e2 + fc_q + fc_k;

		fc_e10 = fc_q;

		fc_vr = fc_mulShiftAll(fc_m2, DOUBLE_POW5_INV_SPLIT[fc_q], fc_i, &fc_vp, &fc_vm, fc_mmShift);

		if (fc_q <= 21)
		{
			/*
			 * 这应该使用 q <= 22，但我认为 21 也是安全的。更小
			 * 的值可能仍然是安全的，但推理起来更困难。
			 *
			 * 如果有的话，mp、mv 和 mm 只能有一个是 5 的倍数。
			 */
			const uint32 fc_mvMod5 = (uint32) (fc_mv - 5 * div5(fc_mv));

			if (fc_mvMod5 == 0)
			{
				fc_vrIsTrailingZeros = fc_multipleOfPowerOf5(fc_mv, fc_q);
			}
			else if (fc_acceptBounds)
			{
				/*----
				 * 同样为 min(e2 + (~mm & 1), pow5Factor(mm)) >= q
				 * <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q
				 * <=> true && pow5Factor(mm) >= q，因为 e2 >= q。
				 *----
				 */
				fc_vmIsTrailingZeros = fc_multipleOfPowerOf5(fc_mv - 1 - fc_mmShift, fc_q);
			}
			else
			{
				/* 同样为 min(e2 + 1, pow5Factor(mp)) >= q。 */
				fc_vp -= fc_multipleOfPowerOf5(fc_mv + 2, fc_q);
			}
		}
	}
	else
	{
		/*
		 * 这个表达式比 max(0, log10Pow5(-e2) - 1) 稍快。
		 */
		const uint32 fc_q = log10Pow5(-fc_e2) - (-fc_e2 > 1);
		const int32 fc_i = -fc_e2 - fc_q;
		const int32 fc_k = pow5bits(fc_i) - DOUBLE_POW5_BITCOUNT;
		const int32 fc_j = fc_q - fc_k;

		fc_e10 = fc_q + fc_e2;

		fc_vr = fc_mulShiftAll(fc_m2, DOUBLE_POW5_SPLIT[fc_i], fc_j, &fc_vp, &fc_vm, fc_mmShift);

		if (fc_q <= 1)
		{
			/*
			 * {vr,vp,vm} 是尾随零，如果 {mv,mp,mm} 至少有 q
			 * 个尾随 0 位。
			 */
			/* mv = 4 * m2，因此它总是至少有两个尾随 0 位。 */
			fc_vrIsTrailingZeros = true;
			if (fc_acceptBounds)
			{
				/*
				 * mm = mv - 1 - mmShift，因此当且仅当
				 * mmShift == 1 时它有 1 个尾随 0 位。
				 */
				fc_vmIsTrailingZeros = fc_mmShift == 1;
			}
			else
			{
				/*
				 * mp = mv + 2，因此它总是至少有 1 个尾随 0 位。
				 */
				--fc_vp;
			}
		}
		else if (fc_q < 63)
		{
			/* TODO(ulfjack): 在这里使用更紧的边界。 */
			/*
			 * 我们需要计算 min(ntz(mv), pow5Factor(mv) - e2) >= q - 1
			 */
			/* <=> ntz(mv) >= q - 1 && pow5Factor(mv) - e2 >= q - 1 */
			/* <=> ntz(mv) >= q - 1 （e2 为负且 -e2 >= q） */
			/* <=> (mv & ((1 << (q - 1)) - 1)) == 0 */

			/*
			 * 我们还需要确保左移不会
			 * 溢出。
			 */
			fc_vrIsTrailingZeros = fc_multipleOfPowerOf2(fc_mv, fc_q - 1);
		}
	}

	/*
	 * 第 4 步：在合法表示的区间中找到最短的小数表示。
	 */
	uint32		fc_removed = 0;
	uint8		fc_lastRemovedDigit = 0;
	uint64		fc_output;

	/* 平均而言，我们移除 ~2 位数字。 */
	if (fc_vmIsTrailingZeros || fc_vrIsTrailingZeros)
	{
		/* 一般情况，发生得很少（~0.7%）。 */
		for (;;)
		{
			const uint64 fc_vpDiv10 = div10(fc_vp);
			const uint64 fc_vmDiv10 = div10(fc_vm);

			if (fc_vpDiv10 <= fc_vmDiv10)
				break;

			const uint32 fc_vmMod10 = (uint32) (fc_vm - 10 * fc_vmDiv10);
			const uint64 fc_vrDiv10 = div10(fc_vr);
			const uint32 fc_vrMod10 = (uint32) (fc_vr - 10 * fc_vrDiv10);

			fc_vmIsTrailingZeros &= fc_vmMod10 == 0;
			fc_vrIsTrailingZeros &= fc_lastRemovedDigit == 0;
			fc_lastRemovedDigit = (uint8) fc_vrMod10;
			fc_vr = fc_vrDiv10;
			fc_vp = fc_vpDiv10;
			fc_vm = fc_vmDiv10;
			++fc_removed;
		}

		if (fc_vmIsTrailingZeros)
		{
			for (;;)
			{
				const uint64 fc_vmDiv10 = div10(fc_vm);
				const uint32 fc_vmMod10 = (uint32) (fc_vm - 10 * fc_vmDiv10);

				if (fc_vmMod10 != 0)
					break;

				const uint64 fc_vpDiv10 = div10(fc_vp);
				const uint64 fc_vrDiv10 = div10(fc_vr);
				const uint32 fc_vrMod10 = (uint32) (fc_vr - 10 * fc_vrDiv10);

				fc_vrIsTrailingZeros &= fc_lastRemovedDigit == 0;
				fc_lastRemovedDigit = (uint8) fc_vrMod10;
				fc_vr = fc_vrDiv10;
				fc_vp = fc_vpDiv10;
				fc_vm = fc_vmDiv10;
				++fc_removed;
			}
		}

		if (fc_vrIsTrailingZeros && fc_lastRemovedDigit == 5 && fc_vr % 2 == 0)
		{
			/* 即使确切数字是 .....50..0 也要进行四舍五入。 */
			fc_lastRemovedDigit = 4;
		}

		/*
		 * 如果 vr 超出边界或我们需要向上四舍五入，则我们需要
		 * 取 vr + 1。
		 */
		fc_output = fc_vr + ((fc_vr == fc_vm && (!fc_acceptBounds || !fc_vmIsTrailingZeros)) || fc_lastRemovedDigit >= 5);
	}
	else
	{
		/*
		 * 专门处理常见情况（~99.3%）。以下百分比
		 * 是相对于此的。
		 */
		bool		fc_roundUp = false;
		const uint64 fc_vpDiv100 = div100(fc_vp);
		const uint64 fc_vmDiv100 = div100(fc_vm);

		if (fc_vpDiv100 > fc_vmDiv100)
		{
			/* 优化：一次移除两位数字（~86.2 %）。 */
			const uint64 fc_vrDiv100 = div100(fc_vr);
			const uint32 fc_vrMod100 = (uint32) (fc_vr - 100 * fc_vrDiv100);

			fc_roundUp = fc_vrMod100 >= 50;
			fc_vr = fc_vrDiv100;
			fc_vp = fc_vpDiv100;
			fc_vm = fc_vmDiv100;
			fc_removed += 2;
		}

		/*----
		 * 循环迭代次数（大约），未优化
		 * 如上：
		 *
		 * 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%,
		 * 6+: 0.02%
		 *
		 * 循环迭代次数（大约），已优化
		 * 如上：
		 *
		 * 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
		 *----
		 */
		for (;;)
		{
			const uint64 fc_vpDiv10 = div10(fc_vp);
			const uint64 fc_vmDiv10 = div10(fc_vm);

			if (fc_vpDiv10 <= fc_vmDiv10)
				break;

			const uint64 fc_vrDiv10 = div10(fc_vr);
			const uint32 fc_vrMod10 = (uint32) (fc_vr - 10 * fc_vrDiv10);

			fc_roundUp = fc_vrMod10 >= 5;
			fc_vr = fc_vrDiv10;
			fc_vp = fc_vpDiv10;
			fc_vm = fc_vmDiv10;
			++fc_removed;
		}

		/*
		 * 如果 vr 超出边界或我们需要向上四舍五入，则我们需要
		 * 取 vr + 1。
		 */
		fc_output = fc_vr + (fc_vr == fc_vm || fc_roundUp);
	}

	const int32 fc_exp = fc_e10 + fc_removed;

	floating_decimal_64 fc_fd;

	fc_fd.exponent = fc_exp;
	fc_fd.mantissa = fc_output;
	return fc_fd;
}

static inline int fc_to_chars_df(const floating_decimal_64 fc_v, const uint32 fc_olength, char *const fc_result)
{
	/* 步骤 5：打印十进制表示。 */
	int			fc_index = 0;

	uint64		fc_output = fc_v.mantissa;
	int32		fc_exp = fc_v.exponent;

	/*----
	 * 在进入时，mantissa * 10^exp 是需要输出的结果。
	 * 调用者如果需要已经处理了负号。
	 *
	 * 我们想根据输出长度和指数在某处插入小数点，这可能意味着添加零：
	 *
	 *            exp  | 格式
	 *            1+   |  ddddddddd000000
	 *            0    |  ddddddddd
	 *  -1 .. -len+1   |  dddddddd.d 到 d.ddddddddd
	 *  -len ...       |  0.ddddddddd 到 0.000dddddd
	 */
	uint32		fc_i = 0;
	int32		fc_nexp = fc_exp + fc_olength;

	if (fc_nexp <= 0)
	{
		/* -nexp 是在 '.' 后添加的 0 的数量 */
		Assert(fc_nexp >= -3);
		/* 0.000ddddd */
		fc_index = 2 - fc_nexp;
		/* 不需要超过这么多的 0 */
		memcpy(fc_result, "0.000000", 8);
	}
	else if (fc_exp < 0)
	{
		/*
		 * dddd.dddd；在开头留空位，移动小数点到后面
		 */
		fc_index = 1;
	}
	else
	{
		/*
		 * 我们可以通过预先用零填充来节省后面的代码。我们知道
		 * 这种形式的输出数字不会超过 16 位，否则
		 * 我们不会选择定点输出。
		 */
		Assert(fc_exp < 16 && fc_exp + fc_olength <= 16);
		memset(fc_result, '0', 16);
	}

	/*
	 * 我们更喜欢 32 位操作，即使在 64 位平台上。我们最多
	 * 只有 17 位数字，而 uint32 可以存储 9 位数字。如果输出不适合
	 * uint32，我们将截断 8 位数字，这样剩下的就可以适应 uint32。
	 */
	if ((fc_output >> 32) != 0)
	{
		/* 昂贵的 64 位除法。 */
		const uint64 fc_q = div1e8(fc_output);
		uint32		fc_output2 = (uint32) (fc_output - 100000000 * fc_q);
		const uint32 fc_c = fc_output2 % 10000;

		fc_output = fc_q;
		fc_output2 /= 10000;

		const uint32 fc_d = fc_output2 % 10000;
		const uint32 fc_c0 = (fc_c % 100) << 1;
		const uint32 fc_c1 = (fc_c / 100) << 1;
		const uint32 fc_d0 = (fc_d % 100) << 1;
		const uint32 fc_d1 = (fc_d / 100) << 1;

		memcpy(fc_result + fc_index + fc_olength - fc_i - 2, DIGIT_TABLE + fc_c0, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 4, DIGIT_TABLE + fc_c1, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 6, DIGIT_TABLE + fc_d0, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 8, DIGIT_TABLE + fc_d1, 2);
		fc_i += 8;
	}

	uint32		fc_output2 = (uint32) fc_output;

	while (fc_output2 >= 10000)
	{
		const uint32 fc_c = fc_output2 - 10000 * (fc_output2 / 10000);
		const uint32 fc_c0 = (fc_c % 100) << 1;
		const uint32 fc_c1 = (fc_c / 100) << 1;

		fc_output2 /= 10000;
		memcpy(fc_result + fc_index + fc_olength - fc_i - 2, DIGIT_TABLE + fc_c0, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 4, DIGIT_TABLE + fc_c1, 2);
		fc_i += 4;
	}
	if (fc_output2 >= 100)
	{
		const uint32 fc_c = (fc_output2 % 100) << 1;

		fc_output2 /= 100;
		memcpy(fc_result + fc_index + fc_olength - fc_i - 2, DIGIT_TABLE + fc_c, 2);
		fc_i += 2;
	}
	if (fc_output2 >= 10)
	{
		const uint32 fc_c = fc_output2 << 1;

		memcpy(fc_result + fc_index + fc_olength - fc_i - 2, DIGIT_TABLE + fc_c, 2);
	}
	else
	{
		fc_result[fc_index] = (char) ('0' + fc_output2);
	}

	if (fc_index == 1)
	{
		/*
		 * nexp 在这里是 1..15，表示小数点前的位数。值为 16 是不可能的，因为当显示指数达到 15 时，我们将切换到
		 * 科学记数法。
		 */
		Assert(fc_nexp < 16);
		/* gcc 似乎只想为小的 2^n 优化 memmove */
		if (fc_nexp & 8)
		{
			memmove(fc_result + fc_index - 1, fc_result + fc_index, 8);
			fc_index += 8;
		}
		if (fc_nexp & 4)
		{
			memmove(fc_result + fc_index - 1, fc_result + fc_index, 4);
			fc_index += 4;
		}
		if (fc_nexp & 2)
		{
			memmove(fc_result + fc_index - 1, fc_result + fc_index, 2);
			fc_index += 2;
		}
		if (fc_nexp & 1)
		{
			fc_result[fc_index - 1] = fc_result[fc_index];
		}
		fc_result[fc_nexp] = '.';
		fc_index = fc_olength + 1;
	}
	else if (fc_exp >= 0)
	{
		/* 我们之前提供了尾随零，现在只需设置长度。 */
		fc_index = fc_olength + fc_exp;
	}
	else
	{
		fc_index = fc_olength + (2 - fc_nexp);
	}

	return fc_index;
}

static inline int fc_to_chars(floating_decimal_64 fc_v, const bool fc_sign, char *const fc_result)
{
	/* 步骤 5：打印十进制表示。 */
	int			fc_index = 0;

	uint64		fc_output = fc_v.mantissa;
	uint32		fc_olength = fc_decimalLength(fc_output);
	int32		fc_exp = fc_v.exponent + fc_olength - 1;

	if (fc_sign)
	{
		fc_result[fc_index++] = '-';
	}

	/*
	 * 固定点输出的阈值选择与 printf
	 * 默认值相匹配。请注意，to_chars_df 的代码和
	 * DOUBLE_SHORTEST_DECIMAL_LEN 的值对这些阈值非常敏感。
	 */
	if (fc_exp >= -4 && fc_exp < 15)
		return fc_to_chars_df(fc_v, fc_olength, fc_result + fc_index) + fc_sign;

	/*
	 * 如果 v.exponent 恰好为 0，我们可能是通过小整数快速路径到达这里，在这种情况下 v.mantissa 可能包含尾随（十进制）零。对于科学记数法，我们需要将这些零移动到指数中。（对于定点数，这无关紧要，这就是为什么我们在这里而不是上面处理它。）
	 *
	 * 由于我们已经根据旧的十进制长度计算了显示指数（exp），该值在这里不会改变。相反，我们只需减少每移除一个数字的显示长度。
	 *
	 * 如果我们不是通过快速路径到达这里，原始指数通常不会是 0，并且不会有尾随零，因此我们最多只需额外的一个 div10/multiply 成本。通过在除以 10 之前检查是否可以被 2 整除，我们可以回收一半的成本。
	 */
	if (fc_v.exponent == 0)
	{
		while ((fc_output & 1) == 0)
		{
			const uint64 fc_q = div10(fc_output);
			const uint32 fc_r = (uint32) (fc_output - 10 * fc_q);

			if (fc_r != 0)
				break;
			fc_output = fc_q;
			--fc_olength;
		}
	}

	/*----
	 * 打印十进制数字。
	 *
	 * 以下代码等同于：
	 *
	 * for (uint32 i = 0; i < olength - 1; ++i) {
	 *   const uint32 c = output % 10; output /= 10;
	 *   result[index + olength - i] = (char) ('0' + c);
	 * }
	 * result[index] = '0' + output % 10;
	 *----
	 */

	uint32		fc_i = 0;

	/*
	 * 我们更喜欢 32 位操作，即使在 64 位平台上。我们最多
	 * 只有 17 位数字，而 uint32 可以存储 9 位数字。如果输出不适合
	 * uint32，我们将截断 8 位数字，这样剩下的就可以适应 uint32。
	 */
	if ((fc_output >> 32) != 0)
	{
		/* 昂贵的 64 位除法。 */
		const uint64 fc_q = div1e8(fc_output);
		uint32		fc_output2 = (uint32) (fc_output - 100000000 * fc_q);

		fc_output = fc_q;

		const uint32 fc_c = fc_output2 % 10000;

		fc_output2 /= 10000;

		const uint32 fc_d = fc_output2 % 10000;
		const uint32 fc_c0 = (fc_c % 100) << 1;
		const uint32 fc_c1 = (fc_c / 100) << 1;
		const uint32 fc_d0 = (fc_d % 100) << 1;
		const uint32 fc_d1 = (fc_d / 100) << 1;

		memcpy(fc_result + fc_index + fc_olength - fc_i - 1, DIGIT_TABLE + fc_c0, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 3, DIGIT_TABLE + fc_c1, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 5, DIGIT_TABLE + fc_d0, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 7, DIGIT_TABLE + fc_d1, 2);
		fc_i += 8;
	}

	uint32		fc_output2 = (uint32) fc_output;

	while (fc_output2 >= 10000)
	{
		const uint32 fc_c = fc_output2 - 10000 * (fc_output2 / 10000);

		fc_output2 /= 10000;

		const uint32 fc_c0 = (fc_c % 100) << 1;
		const uint32 fc_c1 = (fc_c / 100) << 1;

		memcpy(fc_result + fc_index + fc_olength - fc_i - 1, DIGIT_TABLE + fc_c0, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 3, DIGIT_TABLE + fc_c1, 2);
		fc_i += 4;
	}
	if (fc_output2 >= 100)
	{
		const uint32 fc_c = (fc_output2 % 100) << 1;

		fc_output2 /= 100;
		memcpy(fc_result + fc_index + fc_olength - fc_i - 1, DIGIT_TABLE + fc_c, 2);
		fc_i += 2;
	}
	if (fc_output2 >= 10)
	{
		const uint32 fc_c = fc_output2 << 1;

		/*
		 * 我们不能在这里使用 memcpy：小数点位于这两个数字之间。
		 */
		fc_result[fc_index + fc_olength - fc_i] = DIGIT_TABLE[fc_c + 1];
		fc_result[fc_index] = DIGIT_TABLE[fc_c];
	}
	else
	{
		fc_result[fc_index] = (char) ('0' + fc_output2);
	}

	/* 如有必要，打印小数点。 */
	if (fc_olength > 1)
	{
		fc_result[fc_index + 1] = '.';
		fc_index += fc_olength + 1;
	}
	else
	{
		++fc_index;
	}

	/* 打印指数。 */
	fc_result[fc_index++] = 'e';
	if (fc_exp < 0)
	{
		fc_result[fc_index++] = '-';
		fc_exp = -fc_exp;
	}
	else
		fc_result[fc_index++] = '+';

	if (fc_exp >= 100)
	{
		const int32 fc_c = fc_exp % 10;

		memcpy(fc_result + fc_index, DIGIT_TABLE + 2 * (fc_exp / 10), 2);
		fc_result[fc_index + 2] = (char) ('0' + fc_c);
		fc_index += 3;
	}
	else
	{
		memcpy(fc_result + fc_index, DIGIT_TABLE + 2 * fc_exp, 2);
		fc_index += 2;
	}

	return fc_index;
}

static inline bool fc_d2d_small_int(const uint64 fc_ieeeMantissa,
			  const uint32 fc_ieeeExponent,
			  floating_decimal_64 *fc_v)
{
	const int32 fc_e2 = (int32) fc_ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS;

	/*
	 * 避免在这里使用多个 "return false;"，因为这往往会刺激编译器内联多个 d2d 的副本，这是不可取的。
	 */

	if (fc_e2 >= -DOUBLE_MANTISSA_BITS && fc_e2 <= 0)
	{
		/*----
		 * 由于 2^52 <= m2 < 2^53 且 0 <= -e2 <= 52：
		 *   1 <= f = m2 / 2^-e2 < 2^53。
		 *
		 * 测试有效数的低 -e2 位是否为 0，即分数是否为 0。我们可以在这里使用 ieeeMantissa，因为隐含的 1 位永远无法通过此进行测试；隐含的 1 只能在 e2 < -DOUBLE_MANTISSA_BITS 时作为分数的一部分，我们已经检查过这一点。（例如，0.5 会导致 ieeeMantissa == 0 和 e2 == -53）
		 */
		const uint64 fc_mask = (UINT64CONST(1) << -fc_e2) - 1;
		const uint64 fc_fraction = fc_ieeeMantissa & fc_mask;

		if (fc_fraction == 0)
		{
			/*----
			 * f 是范围 [1, 2^53) 内的整数。
			 * 注意：magnitude 可能包含尾随（十进制）0。
			 * 注意：由于 2^53 < 10^16，因此无需调整 decimalLength()。
			 */
			const uint64 fc_m2 = (UINT64CONST(1) << DOUBLE_MANTISSA_BITS) | fc_ieeeMantissa;

			fc_v->mantissa = fc_m2 >> -fc_e2;
			fc_v->exponent = 0;
			return true;
		}
	}

	return false;
}

/*
 * 将给定双精度数的最短十进制表示存储为调用者提供的缓冲区中的 UNTERMINATED 字符串（其长度必须至少为 DOUBLE_SHORTEST_DECIMAL_LEN-1 字节）。
 *
 * 返回存储的字节数。
 */
int double_to_shortest_decimal_bufn(double fc_f, char *fc_result)
{
	/*
	 * 第一步：解码浮点数，并统一规范化和非规范化情况。
	 */
	const uint64 fc_bits = double_to_bits(fc_f);

	/* 将位解码为符号、尾数和指数。 */
	const bool	fc_ieeeSign = ((fc_bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
	const uint64 fc_ieeeMantissa = fc_bits & ((UINT64CONST(1) << DOUBLE_MANTISSA_BITS) - 1);
	const uint32 fc_ieeeExponent = (uint32) ((fc_bits >> DOUBLE_MANTISSA_BITS) & ((1u << DOUBLE_EXPONENT_BITS) - 1));

	/* 情况区分；对于简单情况提前退出。 */
	if (fc_ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u) || (fc_ieeeExponent == 0 && fc_ieeeMantissa == 0))
	{
		return copy_special_str(fc_result, fc_ieeeSign, (fc_ieeeExponent != 0), (fc_ieeeMantissa != 0));
	}

	floating_decimal_64 fc_v;
	const bool	fc_isSmallInt = fc_d2d_small_int(fc_ieeeMantissa, fc_ieeeExponent, &fc_v);

	if (!fc_isSmallInt)
	{
		fc_v = fc_d2d(fc_ieeeMantissa, fc_ieeeExponent);
	}

	return fc_to_chars(fc_v, fc_ieeeSign, fc_result);
}

/*
 * 将给定的双精度数的最短十进制表示存储为一个
 * 以空字符结束的字符串在调用者提供的缓冲区中（该缓冲区至少要有
 * DOUBLE_SHORTEST_DECIMAL_LEN 字节长）。
 *
 * 返回字符串长度。
 */
int double_to_shortest_decimal_buf(double fc_f, char *fc_result)
{
	const int	fc_index = double_to_shortest_decimal_bufn(fc_f, fc_result);

	/* 终止字符串。 */
	Assert(fc_index < DOUBLE_SHORTEST_DECIMAL_LEN);
	fc_result[fc_index] = '\0';
	return fc_index;
}

/*
 * 返回最短的十进制表示作为一个以空字符结束的 palloc'd
 * 字符串（在后端之外，使用 malloc()）。
 *
 * 调用者负责释放结果。
 */
char * double_to_shortest_decimal(double fc_f)
{
	char	   *const fc_result = (char *) palloc(DOUBLE_SHORTEST_DECIMAL_LEN);

	double_to_shortest_decimal_buf(fc_f, fc_result);
	return fc_result;
}
